use std::collections::VecDeque;

use honeybee::prelude::*;
use honeybee::Result;

use crate::mongo::uid;

#[derive(Default)]
pub struct UidProducer {
    cache: VecDeque<i64>,
}

impl Service for UidProducer {}

#[async_trait::async_trait]
impl Actor for UidProducer {
    fn name(&self) -> &str {
        "UidProducer"
    }

    async fn started(&mut self, _ctx: &mut Context<Self>) -> Result<()> {
        info!("{} started", self.name());
        uid::init(10000).await?;
        Ok(())
    }
}

#[message(result = "i64")]
pub struct Acquire;
#[async_trait::async_trait]
impl Handler<Acquire> for UidProducer {
    async fn handle(&mut self, _ctx: &mut Context<Self>, _: Acquire) -> Result<i64> {
        if let Some(uid) = self.cache.pop_front() {
            return Ok(uid);
        }
        let start = uid::inc_update(10).await?;
        info!("inc uid from {}, inc count:{}", start, 10);
        for uid in start + 1..start + 10 {
            self.cache.push_back(uid);
        }
        Ok(start)
    }
}
